/*
 * @FileName: app_comm.c
 * @Author: GreyQiu qiushaogui@aikosolar.com
 * @Date: 2023-08-21 16:44:35
 * @LastEditors: GreyQiu qiushaogui@aikosolar.com
 * @LastEditTime: 2023-09-26 10:49:21
 * @Description: 
 * 
 * Copyright (c) 2023, All Rights Reserved. 
 */

#include "easy_serial.h"
#include "app_analog.h"
#include "app_comm.h"
#include "app_fsm.h"
#include "app_fault.h"
#include "app_calibration.h"
#include "dev_info.h"
#include "bsp.h"

__attribute__((zero_init)) uint32_t app_start_en __attribute__((at(0x20003800)));

/**
 * 以下为各个命令的handler
 */
void cmd_on_off_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        uint8_t on_off = app_fault_get_bit(FAULT_CMD_OFF_MASK);
        easy_serial_ack(cmd, ACK_SUCCESS, &on_off, 1);
    } else if (rw == OPERATE_W) {
        if (data[0] == 1) {
            app_fault_set_bit(FAULT_CMD_OFF_MASK);
        } else {
            app_fault_clear_bit(FAULT_CMD_OFF_MASK);
        }

        easy_serial_ack(cmd, ACK_SUCCESS, NULL, 0);
    }
}

void cmd_vin_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        uint8_t ack[2];
        uint16_t vin = asignal_get_real_flt(ANALOG_ID_VIN) * 100;
        ack[0] = vin >> 8;
        ack[1] = vin & 0xFF;
        easy_serial_ack(cmd, ACK_SUCCESS, ack, 2);
    }
}

void cmd_iin_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        uint8_t ack[2];
        uint16_t temp = asignal_get_real_flt(ANALOG_ID_IIN) * 100;
        ack[0] = temp >> 8;
        ack[1] = temp & 0xFF;
        easy_serial_ack(cmd, ACK_SUCCESS, ack, 2);
    }
}

void cmd_vout_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        uint8_t ack[2];
        uint16_t temp = asignal_get_real_flt(ANALOG_ID_VOUT) * 100;
        ack[0] = temp >> 8;
        ack[1] = temp & 0xFF;
        easy_serial_ack(cmd, ACK_SUCCESS, ack, 2);
    }
}

void cmd_iout_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        uint8_t ack[2];
        uint16_t temp = asignal_get_real_flt(ANALOG_ID_IOUT) * 100;
        ack[0] = temp >> 8;
        ack[1] = temp & 0xFF;
        easy_serial_ack(cmd, ACK_SUCCESS, ack, 2);
    }
}

void cmd_pin_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        uint16_t temp = (asignal_get_real_flt(ANALOG_ID_IIN) * asignal_get_real_flt(ANALOG_ID_VIN)) * 100;
        uint8_t ack[2];
        ack[0] = temp >> 8;
        ack[1] = temp & 0xFF;
        easy_serial_ack(cmd, ACK_SUCCESS, ack, 2);
    }
}

void cmd_temp_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        uint8_t ack[2];
        uint16_t temp = app_analog_get_temp() * 100;
        ack[0] = temp >> 8;
        ack[1] = temp & 0xFF;
        easy_serial_ack(cmd, ACK_SUCCESS, ack, 2);
    }
}

void cmd_fault_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        uint16_t temp = app_fault_get_bits();
        uint8_t ack[2];
        ack[0] = temp >> 8;
        ack[1] = temp & 0xFF;
        easy_serial_ack(cmd, ACK_SUCCESS, ack, 2);
    }
}

void cmd_all_status_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        uint16_t temp;
        int16_t tmp1;
        uint8_t buf[34];
        uint8_t idx = 0;

        // 开关机状态
        if (fsm_get_status() == STATE_NORMAL) {
            temp = 0;
        } else {
            temp = 1;
        }

//        temp = app_fault_get_bit(FAULT_CMD_OFF_MASK);
        buf[idx++] = temp >> 8;
        buf[idx++] = temp & 0xFF;
        // PV1输入电压
        tmp1 = asignal_get_real_flt(ANALOG_ID_VIN) * 100;
        if (tmp1 < 0) {
            tmp1 = 0;
        }
        buf[idx++] = tmp1 >> 8;
        buf[idx++] = tmp1 & 0xFF;
        // PV1输入电流
        tmp1 = asignal_get_real_flt(ANALOG_ID_IIN) * 100;
        if (tmp1 < 0) {
            tmp1 = 0;
        }
        buf[idx++] = tmp1 >> 8;
        buf[idx++] = tmp1 & 0xFF;
        // PV2输入电压
        temp = 0;
        buf[idx++] = temp >> 8;
        buf[idx++] = temp & 0xFF;
        // PV2输入电流
        temp = 0;
        buf[idx++] = temp >> 8;
        buf[idx++] = temp & 0xFF;
        // PV3输入电压
        temp = 0;
        buf[idx++] = temp >> 8;
        buf[idx++] = temp & 0xFF;
        // PV3输入电流
        temp = 0;
        buf[idx++] = temp >> 8;
        buf[idx++] = temp & 0xFF;
        // PV4输入电压
        temp = 0;
        buf[idx++] = temp >> 8;
        buf[idx++] = temp & 0xFF;
        // PV4输入电流
        temp = 0;
        buf[idx++] = temp >> 8;
        buf[idx++] = temp & 0xFF;
        // Pin
        tmp1 = (asignal_get_real_flt(ANALOG_ID_IIN) * asignal_get_real_flt(ANALOG_ID_VIN)) * 100;
        if (tmp1 < 0) {
            tmp1 = 0;
        }
        buf[idx++] = tmp1 >> 8;
        buf[idx++] = tmp1 & 0xFF;
        // Vout
        tmp1 = asignal_get_real_flt(ANALOG_ID_VOUT) * 100;
        if (tmp1 < 0) {
            tmp1 = 0;
        }
        buf[idx++] = tmp1 >> 8;
        buf[idx++] = tmp1 & 0xFF;
        // Iout
        tmp1 = asignal_get_real_flt(ANALOG_ID_IOUT) * 100;
        if (tmp1 < 0) {
            tmp1 = 0;
        }
        buf[idx++] = tmp1 >> 8;
        buf[idx++] = tmp1 & 0xFF;
        // 电网频率
        temp = 0;
        buf[idx++] = temp >> 8;
        buf[idx++] = temp & 0xFF;
        // 已发电量
        temp = app_analog_get_wh();
        buf[idx++] = (temp >> 24) & 0xFF;
        buf[idx++] = (temp >> 16) & 0xFF;
        buf[idx++] = (temp >> 8) & 0xFF;
        buf[idx++] = temp & 0xFF;
        // 温度
        tmp1 = g_mos_temp * 100;
        buf[idx++] = tmp1 >> 8;
        buf[idx++] = tmp1 & 0xFF;
        // 故障状态
        temp = app_fault_get_bits();
        buf[idx++] = temp >> 8;
        buf[idx++] = temp & 0xFF;

        easy_serial_ack(cmd, ACK_SUCCESS, buf, idx);
    }
}

void cmd_factor_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    uint8_t idx = cmd - CMD_CALIBRATION_VIN;
    if (rw == OPERATE_R) {
        uint8_t ack[4];
        ack[0] = factor[idx].k >> 8;
        ack[1] = factor[idx].k & 0xFF;
        ack[2] = factor[idx].b >> 8;
        ack[3] = factor[idx].b & 0xFF;
        easy_serial_ack(cmd, ACK_SUCCESS, ack, 4);
    } else if (rw == OPERATE_W) {
        uint16_t k1 = (data[0] << 8) + data[1];
        int16_t b1 = (data[2] << 8) + data[3];

        app_calib_config(idx, k1, b1);
        easy_serial_ack(cmd, ACK_SUCCESS, NULL, 0);
    }
}

void cmd_swversion_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        uint32_t temp = g_device_info.swVer;
        uint8_t ack[4];
        ack[0] = (temp >> 24) & 0xFF;
        ack[1] = (temp >> 16) & 0xFF;
        ack[2] = (temp >> 8) & 0xFF;
        ack[3] = (temp >> 0) & 0xFF;
        easy_serial_ack(cmd, ACK_SUCCESS, ack, 4);
    }
}

void cmd_hwversion_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        uint32_t temp = g_device_info.hwVer;
        uint8_t ack[4];
        ack[0] = (temp >> 24) & 0xFF;
        ack[1] = (temp >> 16) & 0xFF;
        ack[2] = (temp >> 8) & 0xFF;
        ack[3] = (temp >> 0) & 0xFF;
        easy_serial_ack(cmd, ACK_SUCCESS, ack, 4);
    }
}

void cmd_boot_unlock_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        uint8_t fault = app_fault_get_bit(FAULT_BOOT_MASK);
        easy_serial_ack(cmd, ACK_SUCCESS, &fault, 1);
    } else if (rw == OPERATE_W) {
        if (data[0] == 0xAB && data[1] == 0xCD) {
            log_debug("cmd_boot_unlock..\n");
            app_fault_set_bit(FAULT_BOOT_MASK);
            easy_serial_ack(cmd, ACK_SUCCESS, NULL, 0);
        } else {
            easy_serial_ack(cmd, ACK_ERROR, NULL, 0);
        }
    }
}

void cmd_jump_boot(uint8_t cmd, uint8_t * buf, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        easy_serial_ack(cmd, ACK_ERROR, NULL, 0); // 不支持读
    } else {
        uint8_t boot_unlock = app_fault_get_bit(FAULT_BOOT_MASK);
        log_debug("cmd_jump_boot.. boot_unlock = %d\n", boot_unlock);
        if (boot_unlock == 1) {
            app_start_en = 0x5A5A5A5A;
            RCC_Reset_Flag_Clear();
            __NVIC_SystemReset(); // 复位从BOOT开始运行
        }
        easy_serial_ack(cmd, ACK_ERROR, NULL, 0);
    }
}

void cmd_boot_jump_app(uint8_t cmd, uint8_t * buf, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        easy_serial_ack(cmd, ACK_ERROR, NULL, 0); // 不支持读
    } else {
        log_debug("cmd_jump_app..\n");
        easy_serial_ack(cmd, ACK_SUCCESS, NULL, 0);
    }
}

void cmd_run_mode_handle(uint8_t cmd, uint8_t * data, uint16_t len, uint8_t rw)
{
    if (rw == OPERATE_R) {
        uint8_t ack[1];
        ack[0] = 0x01; 
        easy_serial_ack(cmd, ACK_SUCCESS, ack, 1);
    }
}

cmd_obj_t cmd_table[CMD_NUM] = {
    {.cmd = CMD_ON_OFF,             .permission = PERMISSION_RW,  .len = 2,  .handler = cmd_on_off_handle},
    // {.cmd = CMD_VIN,                .permission = PERMISSION_R,   .len = 2,  .handler = cmd_vin_handle},
    // {.cmd = CMD_IIN,                .permission = PERMISSION_R,   .len = 2,  .handler = cmd_iin_handle},
    // {.cmd = CMD_VOUT,               .permission = PERMISSION_R,   .len = 2,  .handler = cmd_vout_handle},
    // {.cmd = CMD_IOUT,               .permission = PERMISSION_R,   .len = 2,  .handler = cmd_iout_handle},
    // {.cmd = CMD_PIN,                .permission = PERMISSION_R,   .len = 2,  .handler = cmd_pin_handle},
    // {.cmd = CMD_TEMP,               .permission = PERMISSION_R,   .len = 2,  .handler = cmd_temp_handle},
    // {.cmd = CMD_FAULT,              .permission = PERMISSION_R,   .len = 2,  .handler = cmd_fault_handle},
    {.cmd = CMD_ALL_STATUS,         .permission = PERMISSION_R,   .len = 2,  .handler = cmd_all_status_handle},
    {.cmd = CMD_SW_VERSION,         .permission = PERMISSION_R,   .len = 2,  .handler = cmd_swversion_handle},
    {.cmd = CMD_HW_VERSION,         .permission = PERMISSION_R,   .len = 2,  .handler = cmd_hwversion_handle},
    {.cmd = CMD_CALIBRATION_VIN,    .permission = PERMISSION_RW,  .len = 2,  .handler = cmd_factor_handle},
    {.cmd = CMD_CALIBRATION_IIN,    .permission = PERMISSION_RW,  .len = 2,  .handler = cmd_factor_handle},
    {.cmd = CMD_CALIBRATION_VOUT,   .permission = PERMISSION_RW,  .len = 2,  .handler = cmd_factor_handle},
    {.cmd = CMD_CALIBRATION_IOUT,   .permission = PERMISSION_RW,  .len = 2,  .handler = cmd_factor_handle},
    {.cmd = CMD_BOOT_UNLOCK,        .permission = PERMISSION_RW,  .len = 2,  .handler = cmd_boot_unlock_handle},
    {.cmd = CMD_BOOT_JUMP_BOOT,     .permission = PERMISSION_W,   .len = 2,  .handler = cmd_jump_boot},
    {.cmd = CMD_BOOT_JUMP_APP,      .permission = PERMISSION_W,   .len = 2,  .handler = cmd_boot_jump_app},
    {.cmd = CMD_RUN_MODE,           .permission = PERMISSION_R,   .len = 2,  .handler = cmd_run_mode_handle},
};

void app_comm_handle(uint8_t * buf, uint32_t len)
{
    extern uint16_t wifi_reset_cnt;
    wifi_reset_cnt = 0;
    easy_serial_process(buf, len, cmd_table, sizeof(cmd_table) / sizeof(cmd_obj_t));
}

void app_comm_init(void)
{
    // 注册串口接收完成时的回调
    bsp_wifi_uart_callback_register(app_comm_handle); 
}
